package com.nbcio.cd.aspect;

import com.nbcio.cd.utils.CdPermissionUtils;
import com.nbcio.common.core.exception.ServiceException;
import com.nbcio.common.core.utils.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

/**
 * 云网盘权限控制切面
 *
 * @author nbacheng
 * @date 2024-01-01
 */
@Aspect
@Component
public class CdPermissionAspect {

    @Autowired
    private CdPermissionUtils permissionUtils;

    /**
     * 定义切点：所有云网盘相关的控制器方法
     */
    @Pointcut("execution(* com.nbcio.cd.controller.*.*(..))")
    public void cdControllerMethods() {}

    /**
     * 权限检查前置通知
     */
    @Before("cdControllerMethods()")
    public void checkPermission(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Object[] args = joinPoint.getArgs();

        // 获取方法名
        String methodName = method.getName();
        
        // 上传文件时跳过权限检查（文件还未创建，由Service层负责权限验证）
        if (methodName.equals("uploadFile")) {
            return;
        }
        
        // 创建文件夹时跳过权限检查（文件夹还未创建，由Service层负责权限验证）
        if (methodName.equals("createFolder")) {
            return;
        }
        
        // 下载和预览操作跳过权限检查（接口已配置在 security.excludes 中，允许公开访问）
        if (methodName.equals("downloadFile") || methodName.equals("previewFile") || methodName.equals("previewHtml")) {
            return;
        }
        
        // 重命名操作跳过权限检查（由Service层负责权限验证，支持所有者直接操作）
        if (methodName.equals("renameFile") || methodName.equals("renameFolder")) {
            return;
        }
        
        // 移动和复制操作跳过权限检查（由Service层负责权限验证，支持所有者直接操作）
        if (methodName.equals("moveFile") || methodName.equals("moveFolder") ||
            methodName.equals("copyFile") || methodName.equals("copyFolder")) {
            return;
        }
        
        // 分享操作跳过权限检查（由Service层负责权限验证，支持所有者直接操作）
        if (methodName.equals("createShare") || methodName.startsWith("share")) {
            return;
        }
        
        // 根据方法名和参数进行权限检查
        if (methodName.startsWith("download") || methodName.startsWith("preview")) {
            checkFileReadPermission(args);
        } else if (methodName.startsWith("upload") || methodName.startsWith("create")) {
            checkWritePermission(args);
        } else if (methodName.startsWith("delete") || methodName.startsWith("remove")) {
            checkDeletePermission(args);
        } else if (methodName.startsWith("share")) {
            checkSharePermission(args);
        } else if (methodName.startsWith("rename") || methodName.startsWith("move") || methodName.startsWith("copy")) {
            checkWritePermission(args);
        }
    }

    /**
     * 检查文件读取权限
     */
    private void checkFileReadPermission(Object[] args) {
        Long fileId = extractFileId(args);
        if (fileId != null) {
            try {
                permissionUtils.validateFilePermission(fileId, CdPermissionUtils.PERMISSION_READ, 
                    "您没有读取此文件的权限");
            } catch (RuntimeException e) {
                throw new ServiceException(e.getMessage());
            }
        }
    }

    /**
     * 检查写入权限
     */
    private void checkWritePermission(Object[] args) {
        Long fileId = extractFileId(args);
        Long folderId = extractFolderId(args);
        
        if (fileId != null) {
            try {
                permissionUtils.validateFilePermission(fileId, CdPermissionUtils.PERMISSION_WRITE, 
                    "您没有修改此文件的权限");
            } catch (RuntimeException e) {
                throw new ServiceException(e.getMessage());
            }
        } else if (folderId != null) {
            try {
                permissionUtils.validateFolderPermission(folderId, CdPermissionUtils.PERMISSION_WRITE, 
                    "您没有修改此文件夹的权限");
            } catch (RuntimeException e) {
                throw new ServiceException(e.getMessage());
            }
        }
    }

    /**
     * 检查删除权限
     */
    private void checkDeletePermission(Object[] args) {
        Long fileId = extractFileId(args);
        Long folderId = extractFolderId(args);
        
        if (fileId != null) {
            try {
                permissionUtils.validateFilePermission(fileId, CdPermissionUtils.PERMISSION_DELETE, 
                    "您没有删除此文件的权限");
            } catch (RuntimeException e) {
                throw new ServiceException(e.getMessage());
            }
        } else if (folderId != null) {
            try {
                permissionUtils.validateFolderPermission(folderId, CdPermissionUtils.PERMISSION_DELETE, 
                    "您没有删除此文件夹的权限");
            } catch (RuntimeException e) {
                throw new ServiceException(e.getMessage());
            }
        }
    }

    /**
     * 检查分享权限
     */
    private void checkSharePermission(Object[] args) {
        Long fileId = extractFileId(args);
        Long folderId = extractFolderId(args);
        
        if (fileId != null) {
            try {
                permissionUtils.validateFilePermission(fileId, CdPermissionUtils.PERMISSION_SHARE, 
                    "您没有分享此文件的权限");
            } catch (RuntimeException e) {
                throw new ServiceException(e.getMessage());
            }
        } else if (folderId != null) {
            try {
                permissionUtils.validateFolderPermission(folderId, CdPermissionUtils.PERMISSION_SHARE, 
                    "您没有分享此文件夹的权限");
            } catch (RuntimeException e) {
                throw new ServiceException(e.getMessage());
            }
        }
    }

    /**
     * 从参数中提取文件ID
     */
    private Long extractFileId(Object[] args) {
        for (Object arg : args) {
            if (arg instanceof Long) {
                return (Long) arg;
            } else if (arg instanceof String) {
                try {
                    return Long.parseLong((String) arg);
                } catch (NumberFormatException e) {
                    // 忽略非数字字符串
                }
            }
        }
        return null;
    }

    /**
     * 从参数中提取文件夹ID
     */
    private Long extractFolderId(Object[] args) {
        // 这里可以根据实际的方法参数结构来提取文件夹ID
        // 暂时返回null，实际使用时需要根据具体方法调整
        return null;
    }
}
